package com.xb.system.service.impl;

import com.google.common.hash.BloomFilter;
import com.xb.model.domain.DistinctUser;
import com.xb.model.domain.Users;
import com.xb.system.config.DataConfig;
import com.xb.system.config.UserPhoneBloomFilterConfig;
import com.xb.system.service.DistinctUserService;
import com.xb.system.service.DynamicDataSplitterService;
import com.xb.system.service.FileHandler;
import com.xb.system.service.UsersService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * @author wjh
 * @create 2024-07-23 17:01
 */
@Service
@Slf4j
public class DynamicDataSplitterServiceImpl implements DynamicDataSplitterService {

    @Autowired
    private ApplicationContext applicationContext;

    @Autowired
    @Qualifier("txtFileHandler")
    private FileHandler txtFileHandler;

    @Autowired
    @Qualifier("wordDocumentHandler")
    private FileHandler wordDocumentHandler;

    @Autowired
    @Qualifier("excelDocumentHandler")
    private FileHandler excelDocumentHandler;

    @Autowired
    @Qualifier("htmlFileHandler")
    private FileHandler htmlFileHandler;

    //    @Resource(name = "userPhoneBloomFilter")
//    private BloomFilter<String> userPhoneBloomFilter;
    @Resource
    private UserPhoneBloomFilterConfig userPhoneBloomFilterConfig;
    @Autowired
    private UsersService usersService;

    @Autowired
    private DataConfig dataConfig;
    
    @Resource
    private DistinctUserService distinctUserService;

    /**
     * 姓名脱敏
     *
     * @param name 原来的姓名
     * @return 脱敏后的姓名
     */
    private static String maskName(String name) {
        if (name.length() <= 1) {
            return name;
        }
        int length = name.length();
        StringBuilder maskedName = new StringBuilder();
        for (int i = 0; i < length - 1; i++) {
            maskedName.append("*");
        }
        maskedName.append(name.charAt(length - 1));
        return maskedName.toString();
    }

    /**
     * 姓名脱敏
     *
     * @param
     * @return 脱敏后的姓名
     */
    public List<Users> processLine(String line, BloomFilter<String> bloomFilter) {
        String[] parts = line.split("\\s+");  // 按空白字符分割数据
        if (parts.length < Math.max(dataConfig.getPhoneIndex(), dataConfig.getNameIndex()) + 1 || !parts[dataConfig.getPhoneIndex()].matches("^1[3456789]\\d{9}$")) {
            return null;  // 数据列数少于2或者手机号格式不匹配，直接返回
        }

        // TODO 把手机号对应的下标抽离出配置文件
        String phone = parts[dataConfig.getPhoneIndex()];  // 提取手机号

        if (bloomFilter.mightContain(phone)) {
            //将可能重复的用户存入待去重表中
            String name = maskName(parts[dataConfig.getNameIndex()]);
            distinctUserService.save(new DistinctUser(null, phone, name));
            return null;
        }
        List<Users> batch = new ArrayList<>();
        bloomFilter.put(phone);
        // TODO 把name这些需要额外处理的数据对应的下标抽离出配置文件
        String name = maskName(parts[dataConfig.getNameIndex()]);
        batch.add(new Users(null, phone, name));  // 将用户信息添加到批处理列表

        // 处理额外的手机号
        for (int index : dataConfig.getExtraPhoneIndexes()) {
            if (index < parts.length) {
                String extraPhone = parts[index].trim();
                if (extraPhone.matches("^1[3456789]\\d{9}$")) {
                    if (!bloomFilter.mightContain(extraPhone)) {
                        batch.add(new Users(null, extraPhone, name));  // 将额外的手机号与相同姓名一起添加到批处理列表
                        bloomFilter.put(extraPhone);
                    } else {
                        name = maskName(name);
                        distinctUserService.save(new DistinctUser(null, extraPhone, name));
                    }
                }
            }
        }
        return batch;
    }

    @Override
    public void splitData(String file) throws IOException {
        // String contentType = file.getContentType();

        // 根据文件类型选择处理器
        String handlerBeanName = determineHandlerBeanName(file);

        // 通过 Spring 的依赖注入获取对应的处理器类
        FileHandler fileHandler = getFileHandler(handlerBeanName);
        if (fileHandler == null) {
            throw new IllegalStateException("未找到处理程序的bean: " + handlerBeanName);
        }

        // 调用处理器类的方法处理文件
        fileHandler.handleFile(file);
    }

    private String determineHandlerBeanName(String contentType) {
        String handlerBeanName;
        String fileExtension = contentType.substring(contentType.lastIndexOf(".") + 1);
        switch (fileExtension.toLowerCase()) {
            case "txt":
                handlerBeanName = "txtFileHandler";
                break;
            case "doc":
            case "docx":
                handlerBeanName = "wordDocumentHandler";
                break;
            case "xls":
            case "xlsx":
                handlerBeanName = "excelDocumentHandler";
                break;
            case "html":
                handlerBeanName = "htmlFileHandler";
                break;
            default:
                throw new IllegalArgumentException("不支持的文件类型:" + fileExtension);
        }
        return handlerBeanName;
    }

    // 根据 handlerBeanName 获取 FileHandler bean
    private FileHandler getFileHandler(String handlerBeanName) {
        return applicationContext.getBean(handlerBeanName, FileHandler.class);
    }

    // TODO 去重的逻辑提前到解析后的下一步
    public void saveBatch(List<Users> batch) {
        usersService.saveBatch(batch);
        batch.clear();
    }
}
